package com.inspectortime.timestamp;

import java.io.Serializable;
import java.util.Date;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.EmptyInterceptor;
import org.hibernate.Transaction;
import org.hibernate.type.Type;

public class TimestampingHibernateInterceptor extends EmptyInterceptor {

	private static final long serialVersionUID = 8789043573660784186L;

	protected static Log log = LogFactory.getLog(TimestampingHibernateInterceptor.class);
	
	private int updates;

	private int creates;

	private int loads;

	public void onDelete(Object entity, Serializable id, Object[] state,
			String[] propertyNames, Type[] types) {
		// do nothing
	}

	public boolean onFlushDirty(Object entity, Serializable id,
			Object[] currentState, Object[] previousState,
			String[] propertyNames, Type[] types) {

		if (entity instanceof Timestamped) {
			updates++;
			for (int i = 0; i < propertyNames.length; i++) {
				if ("lastModifiedTime".equals(propertyNames[i])) {
					Date rightNow = new Date();
					currentState[i] = rightNow;
					//log.trace("onFlushDirty: Set lastModifiedTime on " + entity.getClass().getName() + " to " + rightNow.getTime());
					return true;
				}
			}
		}
		return false;
	}

	public boolean onLoad(Object entity, Serializable id, Object[] state,
			String[] propertyNames, Type[] types) {
		if (entity instanceof Timestamped) {
			loads++;
		}
		return false;
	}

	public boolean onSave(Object entity, Serializable id, Object[] state,
			String[] propertyNames, Type[] types) {

		boolean madeChange = false;
		Date rightNow = new Date();
		if (entity instanceof Timestamped) {
			creates++;
			for (int i = 0; i < propertyNames.length; i++) {
				if ("createdTime".equals(propertyNames[i])) {
					if (state[i] == null) {
						state[i] = rightNow;
						madeChange = true;	
						//log.trace("onSave: Set createdTime on " + entity.getClass().getName() + " to " + rightNow.getTime());
					}										
				}
				if ("lastModifiedTime".equals(propertyNames[i])) {
					state[i] = rightNow;
					madeChange = true;					
					//log.trace("onSave: Set lastModifiedTime on " + entity.getClass().getName() + " to " + rightNow.getTime());
				}
			}
		}
		if (madeChange) {
			return true;
		}
		return false;
	}

	public void afterTransactionCompletion(Transaction tx) {
		if (tx.wasCommitted()) {
			log.trace("Creations: " + creates + ", Updates: "
					+ updates + ", Loads: " + loads);
		}
		updates = 0;
		creates = 0;
		loads = 0;
	}

}
